import java.util.ArrayList;
import java.util.HashMap;
import java.util.Vector;

public class Cpm {
	Plan plan;

	
	
	Cpm(Plan plan) {
		this.plan = plan;
		plan.start().setEarliestStartTime(0);
	
	}

	public Tuple<Integer, ArrayList<Action>> findLongPath(Action action) {
		Tuple<Integer, ArrayList<Action>> maxPathLength = new Tuple<Integer, ArrayList<Action>>(
				0, new ArrayList<Action>());

		
		Tuple<Integer, ArrayList<Action>> temp = null;
		
		
		if (action.equals(plan.start())) {
			action.setEarliestStartTime(0);
			action.setLatestStartTime(0);
			
			maxPathLength.b().add(action);
			return maxPathLength;
		}
		for (Action a : getCasaulLinkedActions(plan, action)) {
			temp = findLongPath(a);
			
			if ((temp.a()) > maxPathLength.a()) {
				maxPathLength = temp;
			}
		}
		action.setEarliestStartTime(maxPathLength.a());
		action.setLatestStartTime(maxPathLength.a());

		maxPathLength.setA(maxPathLength.a().intValue() + action.getDuration());


		maxPathLength.b().add(action);
		
		return maxPathLength;
	}

	public ArrayList<Action> parallelize(ArrayList<Action> readyActions,
			Action act) {

		ArrayList<Action> linked = getCasaulLinkedActions(plan, act);

		for (Action a : linked) {
		
			
			if (!readyActions.contains(a)) {
				//setParTime sets a's starting time  
				setParTime(a, readyActions);
				readyActions.add(a);
				
			}

			readyActions = parallelize(readyActions, a);
		}

		return readyActions;

		// if not parallelizable with an action in the critical path
		// (already added)
		// then sett the earliest starting time to that actions earliest
		// sarting time + duration.

	}

	private void setParTime(Action a, ArrayList<Action> readyActions) {

		if (!a.isParallelizable()) {
			int startTime = a.getEarliestStartTime();
			int endTime = startTime + a.getDuration();
			for (Action ready : readyActions) {
				if (!ready.isParallelizable()
						&& (ready.getLatestStartTime() > endTime)
						&& (startTime < ready.getEarliestStartTime())) {
					a.setEarliestStartTime(ready.getEarliestStartTime()
							+ ready.getDuration());
					a.setLatestStartTime(ready.getEarliestStartTime()
							+ ready.getDuration());

				}
			}
		}
		else{
			// readyActions.add(arg0, arg1)
		}

	}

	private ArrayList<Action> getCasaulLinkedActions(Plan p, Action act) {
		ArrayList<Action> actions = new ArrayList<Action>();
		for (CausalLink a : p.getCausalLinks()) {
			if (a.getTo().equals(act)) {
				actions.add(a.getFrom());
			}
		}
		return actions;
	}
}
